// polyv-api-utils.js
import CryptoJS from 'crypto-js';

/**
 * 保利威API工具类
 */
class PolyvAPI {
  /**
   * 生成MD5哈希
   * @param {string} str - 要哈希的字符串
   * @returns {string} MD5哈希值(大写)
   */
  static md5(str) {
    return CryptoJS.MD5(str).toString().toUpperCase();
  }

  /**
   * 扁平化对象参数（处理嵌套对象）
   * @param {Object} obj - 要扁平化的对象
   * @param {string} [prefix=''] - 键前缀
   * @returns {Object} 扁平化后的对象
   */
  static flattenParams(obj, prefix = '') {
    return Object.keys(obj).reduce((acc, key) => {
      const value = obj[key];
      const fullKey = prefix ? `${prefix}.${key}` : key;

      if (value === null || value === undefined) {
        return acc;
      }

      if (typeof value === 'object' && !Array.isArray(value)) {
        Object.assign(acc, this.flattenParams(value, fullKey));
      } else {
        acc[fullKey] = String(value);
      }

      return acc;
    }, {});
  }

  /**
   * 实时生成保利威API签名
   * @param {Object} params - 请求参数(包含嵌套对象)
   * @param {string} appSecret - 保利威应用密钥
   * @returns {{sign: string, timestamp: number}} 签名和时间戳
   */
  static generateSign(params, appSecret) {
    const timestamp = Date.now();
    const signParams = { ...params, timestamp };

    // 扁平化参数
    const flatParams = this.flattenParams(signParams);

    // 按ASCII码排序参数名
    const sortedKeys = Object.keys(flatParams).sort();

    // 拼接键值对
    const paramString = sortedKeys
      .map((key) => `${key}${flatParams[key]}`)
      .join('');

    // 生成签名
    const signString = `${appSecret}${paramString}${appSecret}`;
    const sign = this.md5(signString);

    return { sign, timestamp };
  }

  /**
   * 创建保利威频道
   * @param {Object} config - 配置对象
   * @param {string} config.appId - 应用ID
   * @param {string} config.appSecret - 应用密钥
   * @param {Object} channelConfig - 频道配置
   * @returns {Promise<Object>} API响应数据
   */
  static async createChannel(config, channelConfig) {
    const { appId, appSecret } = config;
    const { sign, timestamp } = this.generateSign({ appId }, appSecret);

    const apiUrl = new URL('http://api.polyv.net/live/v4/channel/create-init');
    apiUrl.searchParams.append('appId', appId);
    apiUrl.searchParams.append('timestamp', timestamp);
    apiUrl.searchParams.append('sign', sign);

    try {
      const response = await fetch(apiUrl.toString(), {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(channelConfig),
      });

      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }

      const data = await response.json();

      if (data.code !== 200) {
        throw new Error(data.message || 'API request failed');
      }

      return data;
    } catch (error) {
      console.error('[PolyvAPI] Create channel error:', error);
      throw error;
    }
  }

  /**
   * 获取频道基本信息
   * @param {Object} config - 配置对象
   * @param {string} config.appId - 应用ID
   * @param {string} config.appSecret - 应用密钥
   * @param {string} channelId - 频道ID
   * @returns {Promise<Object>} 频道信息
   */
  static async getChannelInfo(config, channelId) {
    const { appId, appSecret } = config;
    const timestamp = Date.now().toString();
    const sign = this.md5(`${appSecret}${timestamp}${appId}${channelId}`);

    const apiUrl = new URL('https://api.polyv.net/live/v4/channel/basic/get');
    apiUrl.searchParams.append('appId', appId);
    apiUrl.searchParams.append('channelId', channelId);
    apiUrl.searchParams.append('timestamp', timestamp);
    apiUrl.searchParams.append('sign', sign);

    try {
      const response = await fetch(apiUrl.toString(), {
        method: 'GET',
        headers: { 'Content-Type': 'application/json' },
      });

      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }

      const data = await response.json();

      if (data.code !== 200) {
        throw new Error(data.message || 'API request failed');
      }

      return data;
    } catch (error) {
      console.error('[PolyvAPI] Get channel info error:', error);
      throw error;
    }
  }
}

// 导出工具类
export default PolyvAPI;

// 也可以同时导出实例
export const polyvUtils = {
  createChannel: PolyvAPI.createChannel.bind(PolyvAPI),
  getChannelInfo: PolyvAPI.getChannelInfo.bind(PolyvAPI),
  generateSign: PolyvAPI.generateSign.bind(PolyvAPI),
};
